﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExcelUtilities.Data;
using System.Data;

namespace ExcelUtilities
{
    /// <summary>
    /// 将处理在导出文件之前触发的事件的函数
    /// </summary>
    /// <param name="workbook">配置信息</param>
    public delegate void BeforeWriteHandler(Cfg.Workbook workbook);
    /// <summary>
    /// 将处理在导出文件完成后触发的事件的函数
    /// </summary>
    /// <param name="workbookData">导出到excel的数据</param>
    public delegate void AfterWriteHandler(Data.WorkbookData workbookData);

    /// <summary>
    /// excel writer
    /// </summary>
    public abstract class ExcelWriter
    {
        /// <summary>
        /// 将数据导入到excel文件
        /// </summary>
        /// <param name="cfgFile">导出的配置文件</param>
        /// <param name="name">配置项名</param>
        /// <param name="tempFile">模板文件</param>
        /// <param name="workbookData">要导出的数据</param>
        /// <param name="saveFile">将导出到的文件名</param>
        public void Write(string cfgFile, string name, string tempFile, WorkbookData workbookData, string saveFile)
        {
            var workbookCfg = Cfg.CfgReader.Get(cfgFile, name);
            Write(workbookCfg, tempFile, workbookData);
            Save(saveFile);
            PreWrited(workbookData);
        }
        /// <summary>
        /// 将数据导入到stream
        /// </summary>
        /// <param name="cfgFile">导出的配置文件</param>
        /// <param name="name">配置项名</param>
        /// <param name="tempFile">模板文件</param>
        /// <param name="workbookData">要导出的数据</param>
        /// <param name="stream">将导出到的Stream</param>
        public void Write(string cfgFile, string name, string tempFile, WorkbookData workbookData, System.IO.Stream stream)
        {
            var workbookCfg = Cfg.CfgReader.Get(cfgFile, name);
            Write(workbookCfg, tempFile, workbookData);
            Save(stream);
            PreWrited(workbookData);
        }
        /// <summary>
        /// 将数据导入到excel文件
        /// </summary>
        /// <param name="cfgFile">导出的配置文件</param>
        /// <param name="name">配置项名</param>
        /// <param name="tempFile">模板文件</param>
        /// <param name="workbookData">要导出的数据</param>
        /// <param name="saveFile">将导出到的文件名</param>
        public void Write(Cfg.Workbook workbookCfg, string tempFile, WorkbookData workbookData, string saveFile)
        {
            Write(workbookCfg, tempFile, workbookData);
            Save(saveFile);
            PreWrited(workbookData);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="workbookCfg"></param>
        /// <param name="tempFile"></param>
        /// <param name="workbookData"></param>
        /// <param name="stream"></param>
        public void Write(Cfg.Workbook workbookCfg, string tempFile, WorkbookData workbookData, System.IO.Stream stream)
        {
            Write(workbookCfg, tempFile, workbookData);
            Save(stream);
            PreWrited(workbookData);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cfgFile">导出的配置文件</param>
        /// <param name="name">配置项名</param>
        /// <param name="tempFile">模板文件</param>
        /// <param name="workbookData">要导出的数据</param>
        private void Write(Cfg.Workbook workbookCfg, string tempFile, WorkbookData workbookData)
        { 
            Open(tempFile);

            if (OnBeforeWrite != null)
            {
                OnBeforeWrite(workbookCfg);
            }
            foreach (var sheetData in workbookData.SheetDatas)
            {
                var workSheet = workbookCfg.Worksheets.FirstOrDefault(m => string.Equals(m.SheetName, sheetData.Name, StringComparison.OrdinalIgnoreCase));
                if (workSheet == null)
                {
                    continue;
                }
                //TODO:导出单元格数据
                foreach (var cellData in sheetData.CellDatas)
                {
                    var cell = workSheet.Cells.FirstOrDefault(c => string.Equals(c.Name, cellData.Key, StringComparison.OrdinalIgnoreCase));
                    if (cell != null)
                    {
                        SetCellValue(workSheet.SheetName, cell.Address, cellData.Value);
                    }
                }
                //导入数据表数据
                foreach (var tableData in sheetData.TableDatas)
                {
                    var range = workSheet.Ranges.SingleOrDefault(m => string.Equals(m.Name, tableData.Name, StringComparison.OrdinalIgnoreCase));
                    if (range == null)
                    {
                        continue;
                    }
                    var row = range.StartRow;
                    foreach (var rowData in tableData.RowDatas)
                    {
                        foreach (var kv in rowData)
                        {
                            var col = range.Columns.SingleOrDefault(m => string.Equals(m.Name, kv.Key, StringComparison.OrdinalIgnoreCase));
                            if (col != null)
                            {
                                SetCellValue(workSheet.SheetName, row, col.Order, kv.Value);
                            }
                        }
                        row++;
                    }
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="workbookData"></param>
        private void PreWrited(WorkbookData workbookData)
        {
            Close();

            if (OnAfterWrite != null)
            {
                OnAfterWrite(workbookData);
            }
        }
        
        #region

        /// <summary>
        /// 打开文件
        /// </summary>
        /// <param name="tempFile">模板文件</param>
        protected abstract void Open(string tempFile);
        /// <summary>
        /// 关闭，导出完成后调用
        /// </summary>
        protected abstract void Close();
        /// <summary>
        /// 导出到excel文件
        /// </summary>
        /// <param name="savefile">将导出到的excek文件</param>
        protected abstract void Save(string savefile);
        /// <summary>
        /// 导出到Stream
        /// </summary>
        /// <param name="stream"></param>
        protected abstract void Save(System.IO.Stream stream);

        /// <summary>
        /// 给单元格赋值
        /// </summary>
        /// <param name="sheetOrder">第几个工作表（从1开始）</param>
        /// <param name="cellAddress">单元格地址</param> 
        /// <param name="value">将赋给单元格的值</param>
        protected abstract void SetCellValue(int sheetOrder, string cellAddress, object value);
        /// <summary>
        /// 给单元格赋值
        /// </summary>
        /// <param name="sheetOrder">第几个工作表（从1开始）</param>
        /// <param name="row">单元格在第几行(从1开始)</param>
        /// <param name="col">单元格在第几列(从1开始)</param>
        /// <param name="value">将赋给单元格的值</param>
        protected abstract void SetCellValue(int sheetOrder, int row, int col, object value);
        /// <summary>
        /// 给单元格赋值
        /// </summary>
        /// <param name="sheetName">工作表名</param>
        /// <param name="cellAddress">单元格地址</param>
        /// <param name="value">将赋给单元格的值</param>
        protected abstract void SetCellValue(string sheetName, string cellAddress, object value);
        /// <summary>
        /// 给单元格赋值
        /// </summary>
        /// <param name="sheetName">工作表名</param>
        /// <param name="row">单元格在第几行(从1开始)</param>
        /// <param name="col">单元格在第几列(从1开始)</param>
        /// <param name="value">将赋给单元格的值</param>
        protected abstract void SetCellValue(string sheetName, int row, int col, object value);

        /// <summary>
        /// 在导出excel之前触发该事件
        /// </summary>
        public event BeforeReadHandler OnBeforeWrite;
        /// <summary>
        /// 在导出excel之后触发该事件
        /// </summary>
        public event AfterWriteHandler OnAfterWrite;

        #endregion
    }
}